# coding:utf-8

from . import api
from flask import g, request, jsonify, current_app, session
from ihome.utils.commons import login_required
from ihome.utils.response_code import RET
from ihome import redis_store, db, constants
from ihome.models import User
from sqlalchemy.exc import IntegrityError

#  使用werkzeug.security 中的generate_password_hash 进行加密  check_password_hash 进行解密
from werkzeug.security import generate_password_hash, check_password_hash
import re


@api.route("/users", methods=["POST"])
def register():
    """
    注册
    请求的参数  手机号码、短信验证码、密码、确认密码
    :return:
    """
    req_dict = request.get_json()
    mobile = req_dict.get("mobile")
    sms_code = req_dict.get("sms_code")
    password1 = req_dict.get("password1")
    password2 = req_dict.get("password2")

    if not all([mobile, sms_code, password1, password2]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不完整")

    # 判断手机号格式
    if not re.match(r"1([345789][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}", mobile):
        return jsonify(errno=RET.PARAMERR, errmsg="手机号码格式错误")

    if password1 != password1:
        return jsonify(errno=RET.PARAMERR, errmsg="输入的密码不一致")

    # 从redis 中取出短信验证码
    try:
        real_sms_code = redis_store.get("sms_code_%s" % mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="读取真实的短信验证码异常")

    # 判断短信验证码是否过期
    if real_sms_code is None:
        return jsonify(errno=RET.NODATA, errmsg="短信验证码失效")

    # 判断用户填写的验证码是否正确
    if real_sms_code.decode() != sms_code:
        return jsonify(errno=RET.PARAMERR, errmsg="验证码输入错误")

    # 保存用户注册的数据到数据库中
    user = User(name=mobile, mobile=mobile)
    user.password(password1)  #   在数据库中保存加密后的password

    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        # 数据操作错误后回滚
        db.session.rollback()
        # 表示手机号出现了重复
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAEXIST, errmsg="手机号已存在")

    # 保存登录状态到session中
    session["name"] = mobile
    session["mobile"] = mobile
    session["user_id"] = user.id

    return jsonify(errno=RET.OK, errmsg="注册成功")


@api.route("/login", methods=["POST"])
def login():
    """
    登录：
    手机号 密码 验证图片 图片验证码id
    :return:
    """
    req_dict = request.get_json()
    mobile = req_dict.get("mobile")
    password = req_dict.get("password")
    # image_code_id = req_dict.get("image_code_id")
    # image_code = req_dict.get("image_code")


    # 取出图片    if not all([mobile, password]):
        # 判断参数是否完整
        return jsonify(errno=RET.PARAMERR, errmsg="参数不完整")

    # try:
    #     real_image_code = redis_store.get("image_code_%s" % image_code_id)
    # except Exception as e:
    #     current_app.logger.error(e)
    #     return jsonify(errno=RET.DBERR, errmsg="redis数据库异常")
    # # 判断图片验证码是否过期
    # if real_image_code is None:
    #     return jsonify(errno=RET.NODATA, errmsg="图片验证码过期")

    # 删除数据中的的图片验证码
    # try:
    #     redis_store.delete("image_code_%s" % image_code_id)
    # except Exception as e:
    #     current_app.logger.error(e)

    # 验证图片验证码是否正确
    # if (real_image_code.decode().lower() != image_code.lower()):
    #     return jsonify(errno=RET.DATAERR, errmsg="图片验证码错误")

    # 判断用户是否超过限制,如果超出限制 则返回
    # Redis记录  "access_nums_请求的ip次数
    user_ip = request.remote_addr  # 用户的ip地址
    try:
        nums = redis_store.get("num_%s" % user_ip)
    except Exception as e:
        current_app.logger.error(e)
    else:
        if nums is not None and int(nums) >= constants.LOGIN_ERROR_MAX_TIMES:
            return jsonify(errno=RET.REQERR, errmsg="错误的次数过多，请稍后重试")

    # 查询用户的输入信息的对应数据
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="获取用户信息失败")

    if user is None or not user.check_password(password):
        # 如果验证是失败，记录失败的个数，返回失败信息
        try:
            # redis中incr 可以对字符串类型的数字数据进行加一操作
            redis_store.incr("num_%s" % user_ip)
            redis_store.expire("num_%s" % user_ip, constants.LOGIN_ERROR_FORBID_TIME)
        except Exception as e:
            current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg="用户名或密码错误")

    # 验证成功 保存登录状态 在session中
    session["name"] = user.name
    session["mobile"] = user.mobile
    session["user_id"] = user.id

    return jsonify(errno=RET.OK, errmsg="登录成功")


@api.route("/check_login", methods=["GET"])
def check_login():
    """检查登录状态"""
    # 尝试从session 中获取用户的名字
    name = session.get("name")
    if name is not None:
        return jsonify(errno=RET.OK, errmsg="success", data={"name": name})
    else:
        return jsonify(errno=RET.SESSIONERR, errmsg="fail")


@api.route("/login_out", methods=["DELETE"])
def login_out():
    """登出"""
    session.clear()
    return jsonify(errno=RET.OK,errmsg="success")


@api.route("/change_pwd", methods=["PUT"])
def change_pwd():
    """
        修改密码
        请求的参数  手机号码、短信验证码、新密码
        :return:
        """
    req_dict = request.get_json()
    mobile = req_dict.get("mobile")
    sms_code = req_dict.get("sms_code")
    password = req_dict.get("password")


    if not all([mobile, sms_code, password]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不完整")

    # 判断手机号格式
    if not re.match(r"1([345789][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}", mobile):
        return jsonify(errno=RET.PARAMERR, errmsg="手机号码格式错误")

    # 从redis 中取出短信验证码
    try:
        real_sms_code = redis_store.get("sms_code_%s" % mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="读取真实的短信验证码异常")

    # 判断短信验证码是否过期
    if real_sms_code is None:
        return jsonify(errno=RET.NODATA, errmsg="短信验证码失效")

    # 删除redis中的短信验证码， 防止用户重复使用校验
    # try:
    #     redis_store.delete("sms_code_%s" % mobile)
    # except Exception as e:
    #     current_app.logger.error(e)

    # 判断用户填写的验证码是否正确
    if real_sms_code.decode() != sms_code:
        return jsonify(errno=RET.PARAMERR, errmsg="验证码输入错误")

    # 修改用户的数据到数据库中
    user = db.session.query(User).filter_by(mobile=mobile).first()
    user.password(password)  # 在数据库中保存加密后的password

    try:
        db.session.commit()
    except Exception as e:
        # 数据操作错误后回滚
        db.session.rollback()
        # 表示手机号出现了重复
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAEXIST, errmsg="手机号已存在")

    return jsonify(errno=RET.OK, errmsg="修改成功")


@api.route("/mine/change_pwd", methods=["PUT"])
@login_required
def mine_change_pwd():
    """
        使用已知的密码修改密码
        请求的参数  旧密码、新密码
        :return:
        """
    req_dict = request.get_json()
    user_id = g.user_id
    old_password = req_dict.get("old_password")
    new_password = req_dict.get("new_password")

    if not all([old_password, new_password]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不完整")

    # 修改用户的数据到数据库中
    user = db.session.query(User).filter_by(id=user_id).first()
    # 输入旧密码与原始密码做对比
    if user is None or not user.check_password(old_password):
        return jsonify(errno=RET.DATAERR, errmsg="输入的密码有误")

    user.password(new_password)  # 在数据库中保存加密后的password

    try:
        db.session.commit()
    except Exception as e:
        # 数据操作错误后回滚
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAEXIST, errmsg="修改失败")

    return jsonify(errno=RET.OK, errmsg="修改成功")